package chapter26;

import java.time.Instant;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.Supplier;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2019/2/28 18:37
 */
public class AsyncTest {
    private static final ExecutorService exec = Executors.newFixedThreadPool(10);
    private static Random random = new Random();
    private static Callable<Integer> externalTask = () -> {
        int time = delayRandom(20, 2000);
        return time;
    };
    private static Supplier<Integer> externalTask2 = () -> {
        int time = delayRandom(20, 2000);
        return time;
    };

    private static int delayRandom(int min, int max) {
        int milli = max > min ? random.nextInt(max - min) : 0;
        System.out.println("begin:" + Instant.now());
        try {
            TimeUnit.MILLISECONDS.sleep(milli);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end:" + Instant.now());
        return milli;
    }

    private static Future<Integer> callExternalService() {
        return exec.submit(externalTask);
    }

    private static Future<Integer> callExternalService2() {
        return CompletableFuture.supplyAsync(externalTask2, exec);
    }

    public static void main(String[] args) throws InterruptedException {
        Future<Integer> asyncRet = callExternalService2();
        try {
            Integer ret = asyncRet.get();
            System.out.println(ret);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        CompletableFuture.supplyAsync(externalTask2).whenCompleteAsync((result, ex) -> {
            if (result != null) {
                System.out.println(result);
            }

            if (ex != null) {
                ex.printStackTrace();
            }
        }, exec).join();

        exec.shutdownNow();

        Runnable taskA = () -> {
            System.out.println("this is task A");
        };

        Runnable taskB = () -> {
            System.out.println("this is task B");
        };

        Runnable taskC = () -> {
            System.out.println("this is task C");
        };

        CompletableFuture.runAsync(taskA).thenRun(taskB).thenRun(taskC).join();
    }
}
